/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jigdo.utils;

/**
 *
 * @author John R Sohn
 */
public class ByteUtils {
   
    /**
     * Converts a byte value to an integer value.
     * @param value The byte value.
     * @return The more workable integer value.
     */
    public static int GetUnsigned(byte value)
    {
        return value &0xFF;
    }
    
        
    /**
     * Retrieves an integer value from a byte array segment encoded in little endian format
     * @param src The source array
     * @param index The starting index of the integer value
     * @param length The number of bytes to parse for the integer value
     * @return  The parsed integer value.
     */
     public static long GetIntFromBytes(byte[] src, int index, int length)
    {
        byte[] lenarray = new byte[length];
        
        System.arraycopy(src, index, lenarray, 0,length);
        
        return ByteUtils.GetIntFromArray(jigdo.utils.ByteUtils.ByteArrayToIntArray(lenarray),length);
    }
    
    public static byte[] CopyIntToByteArray(int[] src, int startpos, int length)
    {
        byte[] dest = new byte[length];
        
        for (int x=startpos; x<length; x++)
        {
            dest[x-startpos]= (byte)src[x];
        }
        
        return dest;
    }
    
    /**
     * Converts a java byte[] to more usuable integer values
     * @param src the src bytes to convert
     * @return an integer array
     */
    public static int[] ByteArrayToIntArray(byte[] src)
    {
        int[] dest = new int[src.length];
        
        for (int x =0; x<src.length;x++)
        {
            dest[x] = GetUnsigned(src[x]);
        }
        
        return dest;
    }
    
    /**
     * Accepts a integer array representing byte values as a java byte[]
     * @param src int array representing byte values.
     * @return a byte array representation of the int[] 
     */
    public static byte[] IntArrayToByteArray(int[] src)
    {
        byte[] dest = new byte[src.length];
        
        for (int x =0; x < src.length;x++)
        {
            dest[x] = (byte)src[x];
        }
        
        return dest;
    }
    
    /**
     * Accepts a converted byte[] and length and combines them into a single integer.
     * @param src An integer representation of a byte[] containing a raw unsigned rep of an integer
     * @param length Represents the number of byte values represented
     * @return The combined integer value
     */
     public static long GetIntFromArray(int[] src, int length) {
        long i = 0;
                
        int index = 0;
        
        while (index < length)
        {
           i+=Math.pow(256, index) * src[index];
           index++;
        }
        return i;
    }
     
     /**
      * The jigdo specific Base64 cipher string.
      */
     private static String Jigdo64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
     
    
     /**
      * Outputs a byte value and its binary value to the console.
      * @param value
      */
     public static void OutputByte(byte value)
     {
         OutputByte(value & 0xFF);
     }
     
     /**
      * Outputs an integer and its binary value to the console.
      * @param value an integer value
      */
     public static void OutputByte(int value)
     {
         System.out.printf("Byte: %1$d,  Binary: %2$s\r\n",value, Integer.toBinaryString(value));
     }
     
    /**
     * Returns an integer array of Base64 index values to be applied to a cipher
     * @param src Source byte array to convert
     * @return Integer array representing index values for indexing the encoding cipher
     */
    public static int[] GetBase64Bytes(byte[] src)
    {
      
        int[] result = new int[((int)Math.ceil(src.length*8.0/6.0))];
    

         // # of bits processed in the current byte
         int srcBitsProcessed =0;
         // index of the byte array
         int currByte =0;
         // current byte value in integer form
         int currentByteValue = src[currByte] &0xFF;
         
         // iterate through the results array until finished.
         for (int currResultIndex=0; currResultIndex< result.length;currResultIndex++)
         {
             result[currResultIndex]=0;
             
             for (int currentResultBit=0; currentResultBit <6 ; currentResultBit++)
             {
                 
                 result[currResultIndex] = result[currResultIndex] << 1;
                 
                 if (srcBitsProcessed ==8)
                 {
                     currByte++;
                     srcBitsProcessed=0;
                     
                     if (currByte < src.length)
                     {
                         currentByteValue=src[currByte] &0xFF;
                     }
                 }
                 
                 if (currByte < src.length)
                 {
                    
                    result[currResultIndex] = result[currResultIndex] | ((currentByteValue & 0b10000000) >> 7);
                    currentByteValue = currentByteValue << 1;
                    srcBitsProcessed++;
                 }
                 
        
             }  
        }
         
         return result;
    }
    
    /**
     * Returns a Jigdo Base64 representation of a byte array
     * @param src Source byte array
     * @return a Jigdo Specific Base64 representation of the src array
     */
    public static String GetJigdo64 (byte[] src)
    {
        int [] indexes = GetBase64Bytes(src);
      
        String result ="";
        
        for (int srcIndex=0; srcIndex < indexes.length;srcIndex++)
        {
            result+= Jigdo64.charAt(indexes[srcIndex]);
        }
        
        return result;
    }
     
    /**
     * Converts a portion of a byte array to a String
     * @param src Source byte array
     * @param start Starting index of the string
     * @param length Number of bytes to parse
     * @return The parsed string
     */
     public static String GetString(byte[] src, int start, int length)
     {
         String res = "";
         
         for (int x=0; x < length ;x++)
         {
             res+=(char)src[start+x];
         }
         
         return res;
     }
     
     
     
     
     public static  void ConsoleOut(byte[] b)
     {
         boolean first =true;
         
        for (int x=0; x < b.length; x++)
        {
            if (first)
            {
                first = false;
                System.out.print((int)b[x]);
            }
            else
            {
                System.out.print(", ");
                System.out.print((int)b[x]);
            }
            
        }
        
        System.out.println();
     }
}
